use std::cmp::PartialEq;
// 定义信号灯枚举，分别表示三种灯
#[derive(Debug)]
pub enum TrafficLight  {
    Red,
    Green,
    Yellow(bool), // 传入true 表示红转黄，传入false表示绿转黄
}
// 给 TrafficLight 添加方法
impl TrafficLight {
    // 添加返回某种信号灯等待时间的方法
    // 返回值是 u32 类型的方法，
    pub fn time(&self)->u16 {
        match self {
            TrafficLight::Red => {
                30
            },
            TrafficLight::Green => {
                50
            },
            TrafficLight::Yellow(x) => {
                3
            },
        }
    }
    // 该函数返回信号灯的中文名称
    // 返回值是一个字符串，并将字符串的所有权移交到函数外面
    pub fn name(&self)->String {
        match self {
            TrafficLight::Red => {
                String::from("红灯")
            },
            TrafficLight::Green => {
                String::from("绿灯")
            },
            TrafficLight::Yellow(x) => {
                String::from("黄灯")
            },
        }
    }

    // 该函数专门用来类型间的比较，因为我不知道枚举中如何进行比较，就这样简单的绕了一下
    pub fn compare_name(&self) -> String {
        match self {
            TrafficLight::Red => {
                String::from("Red")
            },
            TrafficLight::Green => {
                String::from("Red")
            },
            TrafficLight::Yellow(x) => {
                String::from(format!("黄灯{}", x))
            },
        }
    }

    // 红绿灯转换方法，转换逻辑是红转黄，黄转绿，绿转黄，黄转红
    pub fn switch(&self) -> TrafficLight {
        match self {
            TrafficLight::Red => {
                TrafficLight::Yellow(true)
            },
            TrafficLight::Green => {
                TrafficLight::Yellow(false)
            },
            TrafficLight::Yellow(x) => {
                if true == *x {
                    TrafficLight::Green
                }else{
                    TrafficLight::Red
                }
            },
        }
    }
}

// 为了让枚举在测试的时候可以相互比较，被迫实现了 PartialEq trait
impl PartialEq for TrafficLight {
    fn eq(&self, other: &Self) -> bool {
        // 直接比较枚举对应的名字
        self.compare_name() == other.compare_name()
    }
}

// 写个单元测试测试一下红绿灯转换部分 TDD
#[cfg(test)]
mod tests {
    // use crate::TrafficLight;
    use crate::traffic_light::TrafficLight;

    #[test]
    fn test_get_trafficlight_name () {
        assert_eq!("红灯", TrafficLight::Red.name());
        assert_eq!("黄灯", TrafficLight::Yellow(true).name());
        assert_eq!("黄灯", TrafficLight::Yellow(false).name());
        assert_eq!("绿灯", TrafficLight::Green.name());
    }

    #[test] // 测试红绿灯转换逻辑 
    fn test_light_switch() {
        let light = TrafficLight::Red;
        let light = light.switch(); 
        assert_eq!(TrafficLight::Yellow(true) ,light, "红灯切换应该是黄灯。") ;
        let light = light.switch(); 
        assert_eq!(TrafficLight::Green , light, "红切换黄灯后再次切换是绿灯。") ;
        let light = light.switch(); 
        assert_eq!(TrafficLight::Yellow(false), light, "绿灯切换是黄灯，这里注意是绿切黄所以 Yellow x = false") ;
        let light = light.switch(); 
        assert_eq!(TrafficLight::Red , light, "因为绿切换黄灯，此时黄灯切换是红灯") ;
        let light = light.switch(); 
        assert_eq!(TrafficLight::Yellow(true) , light,"循环往复") ;
    }
}